define(["esri/layers/GraphicsLayer", "esri/geometry/Polyline"], function(Layer, Polyline) {
    var Layer = Layer.createSubclass({
        setData: function(mapView, layer) {
            var me = this;
            var options = layer.layer || {};
            var data = $.extend(true, [], layer.layer.data);
            me.mapView = mapView;
            var mapUtils = mapView.mapUtils;
            me.mapUtils = mapUtils;
            me.layer = layer;
            me.options = options;
            me.i = 0;
            me.data = data;
            me.speed = options.speed || 500;
            me.isLoopPlayback = options.isLoopPlayback;

            if (!data || data.length < 1) {
                if (typeof options.callback == 'function') {
                    options.callback(layer);
                };
                return
            };

            me.init();

        },
        init: function() {
            var me = this;
            var mapView = me.mapView;
            var mapUtils = me.mapUtils;
            var data = me.data;
            var options = me.options;

            me.data = mapUtils.toLngLatArray(mapView, data, options);
            if (options.isShowBaseLine) {
                me.addBasePolyline();
            };

            if (data && data.length > 0) {
                me.initPt();
                me.insertData();
            };

        },
        initPt: function() {
            var me = this;
            var data = me.data;
            if (data[me.i] && data[me.i + 1]) {
                me.insertPt(data[me.i], data[me.i + 1]);
                me.i++;
            };
        },
        continue: function() {
            this.insertData();
        },
        pause: function() {
            this.clearIntervalHandle();
        },
        addBasePolyline: function() {
            var me = this;
            var mapView = me.mapView;
            var mapUtils = me.mapUtils;
            var options = me.options;
            options.expandFactor = options.expandFactor || 2;
            var data = me.data;
            var paths = [];
            data.map(function(item) {
                paths.push([item.x, item.y]);
            });
            var obj = { paths: [paths] };
            var geometry = mapUtils.createPolyline(mapView, obj);
            var sys = options.baseLineSymbol || {
                type: 'simplePolyline',
                style: 'dash',
                color: [255, 0, 0],
                width: 2
            };

            var symbol = mapUtils.createSymbol(mapView, sys);

            var graphic = mapUtils.createGraphic(mapView, {
                geometry: geometry,
                symbol: symbol
            });
            me.add(graphic);

            setTimeout(function() {
                mapUtils.zoomToExtent(mapView, graphic.geometry.extent, {
                    expandFactor: options.expandFactor,
                    xOffset: options.xOffset,
                    yOffset: options.yOffset,
                });
            }, 200);

        },

        insertData: function() {
            var me = this;
            var data = me.data || [];
            if (data.length < 1) {
                return;
            };
            me.clearIntervalHandle();
            me.intervalHandle = setInterval(function() {
                if (me.i >= data.length) {
                    me.i = data.length;
                    me.clearIntervalHandle();
                    // if (typeof me.options.callback == 'function') {//by MHQ 在callback中有动态数据时，多个延时会相互影响
                    //      me.options.callback(me.layer);
                    //   }
                } else {
                    if (me.i > 0) {
                        me.insertLine(data[me.i - 1], data[me.i]);
                    };
                    me.reSetPtSymbol();

                    me.insertPt(data[me.i], data[me.i + 1]);

                    me.i++;
                };
            }, me.speed);

        },
        reSetPtSymbol: function() {
            var me = this;
            var options = me.options;
            if (!options.basePtSymbol) {
                return;
            }
            var mapView = me.mapView;
            var mapUtils = me.mapUtils;

            var graphics = me.graphics.items;

            for (var i = 0; i < graphics.length; i++) {
                if (graphics[i].geometry.type == 'point') {
                    graphics[i].symbol = mapUtils.createSymbol(mapView, options.basePtSymbol);
                };
            };
        },
        insertPt: function(item, nextItem) {
            var me = this;
            var mapView = me.mapView;
            var mapUtils = me.mapUtils;
            var options = me.options;
            var geometry = mapUtils.createPoint(mapView, item);

            var sys = options.dyPtSymbol || {
                type: 'simplePoint',
                style: 'circle',
                color: [0, 255, 255],
                size: 6
            };
            if (options.isCalAngle && nextItem) {
                mapUtils.turf.measurement.rhumbBearing(mapView, item, nextItem, {}).then(function(bearing) {
                    sys.angle = bearing;
                    callback();
                });
            } else {
                callback();
            };

            function callback() {
                var symbol = mapUtils.createSymbol(mapView, sys);
                var graphic = mapUtils.createGraphic(mapView, {
                    geometry: geometry,
                    symbol: symbol,
                    attributes: item
                });
                me.add(graphic);
            };
        },
        insertLine: function(start, end) {
            var me = this;
            var mapView = me.mapView;
            var mapUtils = me.mapUtils;
            var options = me.options;
            var sys = options.dyLineSymbol || {
                type: 'simplePolyline',
                style: 'solid',
                color: [255, 0, 0],
                width: 2
            }
            var symbol = mapUtils.createSymbol(mapView, sys);
            var options = { npoints: 100 };
            mapUtils.turf.measurement.greatCircle(mapView, start, end, options).then(function(greatCircle) {
                let polyline;
                if (me.dyLineGraphic) {
                    polyline = me.dyLineGraphic.geometry.addPath(greatCircle);
                    me.remove(me.dyLineGraphic);
                    // me.dyLineGraphic.symbol = me.dyLineGraphic.symbol;
                } else {
                    polyline = new Polyline();
                    polyline.addPath(greatCircle);
                }

                var polylineGraphic = mapUtils.createGraphic(mapView, {
                    geometry: polyline,
                    symbol: symbol
                });
                me.add(polylineGraphic);
                me.dyLineGraphic = polylineGraphic;

            });
        },
        clearIntervalHandle: function() {
            var me = this;
            if (me.intervalHandle) {
                clearInterval(me.intervalHandle)
                me.intervalHandle = null;
            };

        },
        removeLayer: function(layerName) {
            var me = this;
            this.inherited(arguments);
            me.i = 0;
            me.clearIntervalHandle();
            if (me.layer._realHandle) {
                clearInterval(me.layer._realHandle);
                me.layer._realHandle = null;
            }
        },
        getGraphicLocation: function(mapView, esriEvent) {
            var me = this;
            var location = null;
            var mapUtils = mapView.mapUtils;
            var _geometryType = esriEvent.graphic.geometry.type;
            switch (_geometryType) {
                case mapUtils.Enum.GType.Point:
                    location = me.getPointGraphicLocation(mapView, esriEvent);
                    break;
                case mapUtils.Enum.GType.Polyline:
                    location = me.getPolylineGraphicLocation(mapView, esriEvent);
                    break;
                case mapUtils.Enum.GType.Extent:
                case mapUtils.Enum.GType.Circle:
                case mapUtils.Enum.GType.Polygon:
                    location = me.getPolygonGraphicLocation(mapView, esriEvent);
                    break;
                case mapUtils.Enum.GType.Text:
                    location = me.getTextGraphicLocation(mapView, esriEvent);
                    break;
            };
            return location;
        },
        getPointGraphicLocation: function(mapView, esriEvent) {
            if (!esriEvent || !esriEvent.graphic) {
                return;
            }
            var geometry = esriEvent.graphic.geometry || {};

            var lngFieldName = mapView.getLngFieldName();
            var latFieldName = mapView.getLatFieldName();
            var location = {};
            location[lngFieldName] = geometry.x;
            location[latFieldName] = geometry.y;
            return location;
        },
        getPolylineGraphicLocation: function(mapView, esriEvent) {
            if (!esriEvent || !esriEvent.mapPoint) {
                return;
            }
            var geometry = esriEvent.mapPoint || {};

            var lngFieldName = mapView.getLngFieldName();
            var latFieldName = mapView.getLatFieldName();
            var location = {};
            location[lngFieldName] = geometry.x;
            location[latFieldName] = geometry.y;
            return location;
        },
        getPolygonGraphicLocation: function(mapView, esriEvent) {
            if (!esriEvent || !esriEvent.mapPoint) {
                return;
            }
            var geometry = esriEvent.mapPoint || {};
            var lngFieldName = mapView.getLngFieldName();
            var latFieldName = mapView.getLatFieldName();
            var location = {}
            location[lngFieldName] = geometry.x;
            location[latFieldName] = geometry.y;
            return location;
        },
        getTextGraphicLocation: function(mapView, esriEvent) {
            if (!esriEvent || !esriEvent.graphic) {
                return;
            }
            var geometry = esriEvent.graphic.geometry || {};

            var lngFieldName = mapView.getLngFieldName();
            var latFieldName = mapView.getLatFieldName();
            var location = {};
            location[lngFieldName] = geometry.x;
            location[latFieldName] = geometry.y;
            return location;
        }
    });
    return Layer;
});